/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!		\file		CC_L2D.h
		\date		june 2010
		\author		TNick

		\brief		Contains the definition of CC_L2D class and related


	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	Please read ReadMe.txt and Licence.txt in root folder
	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	These lists are simple chains of objects. Each list must have
	- a header (CC_HDL2D) that holds a pointer to the first item
	- a number of 0 or more items that inherit from CC_L2D (holding only a
	forward and a backward pointer)

*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
#ifndef		__CC_L2D_INC__
#define		__CC_L2D_INC__
#ifdef		__cplusplus
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

class	CC_L2D;
class	CC_HDL2D;

#include	<QtGlobal>
#include	<QtGlobal>

/*  INCLUDES    ============================================================ */
//
//
//
//











/* ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| */
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
/// list header
class	CC_HDL2D {
	//
	//
	//
	//
	/*  DEFINITIONS    --------------------------------------------------------- */
	friend class CC_L2D;

	/*  DEFINITIONS    ========================================================= */
	//
	//
	//
	//
	/*  DATA    ---------------------------------------------------------------- */

protected:

	/// pointer to first element in list
	class	CC_L2D*		Lip1;

	/// number of items that belong to this chain
	int					iCnt;

	/*  DATA    ================================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ----------------------------------------------------------- */
public:

	/// constructor;
	CC_HDL2D()
		{ Lip1 = NULL; iCnt = 0; }

	/// destructor; will free resources;
	virtual				~CC_HDL2D();

	/// remove all items from this list by deleting them
	void				erase		(void);


	/// get the number of items
	inline int			count	(void) const
		{ return iCnt; }


	/// get nth item
	inline CC_L2D*		item	(int i) const;


	/// get first item
	inline CC_L2D*		first	(void)  const
		{ return Lip1; }


	/// get last item
	inline CC_L2D*		last	(void)  const
		{ if (iCnt == 0) return NULL; return item(iCnt-1); }


	/// returns the index of a particular item inside this chain
public:	inline int		itemIndex	( const CC_L2D* pIt)  const;


	/// tell if an item is part of this chain
public:	inline bool		has		( const CC_L2D* pIt)  const;


	/// append an item (insert after last)
	inline void			append	(CC_L2D* pIt);


	/// prepend an item (insert as first item)
	inline void			prepend	(CC_L2D* pIt);


	/// remove the item at given index
	inline void			remove	(int i);

	/// remove a particular item
	inline void			remove	( CC_L2D* pIt);

	/// header is informed about an item being added
	inline void			ackAdd	(CC_L2D* pNew);


	/// header is informed about an item being deleted
	inline void			ackDel	(CC_L2D* pNew);


	/// set first item
	inline void			setFirst(CC_L2D* pNew)
		{ Lip1 = pNew; }


	/// set number of items
	inline void			setCount(int iNew)
		{ iCnt = iNew; }

	/// insert a item at specified index
	void				insert(CC_L2D* p_new, int index);

	/*  FUNCTIONS    =========================================================== */
	//
	//
	//
	//
};	/*	class	CC_HDL2D	*/
//
//
//
//
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
/* ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| */



/* ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| */
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
/// list element
class	CC_L2D {
	//
	//
	//
	//
	/*  DEFINITIONS    --------------------------------------------------------- */
	friend class CC_HDL2D;

	/*  DEFINITIONS    ========================================================= */
	//
	//
	//
	//
	/*  DATA    ---------------------------------------------------------------- */

	/// pointer to next element in list
	class	CC_L2D*		LipN;

	/// pointer to previous element in list
	class	CC_L2D*		LipP;


	/*  DATA    ================================================================ */
	//
	//
	//
	//
	/*  FUNCTIONS    ----------------------------------------------------------- */
public:

	/// constructor; creates a simple, hanging element
	inline				CC_L2D()
		{ LipN = NULL; LipP = NULL; }

	/// constructor; appends this item to the chain managed by pFth
	inline				CC_L2D(CC_HDL2D* pFth)
		{ LipN = NULL; LipP = NULL; pFth->append(this); }

	/// destructor; will free resources;
	virtual				~CC_L2D(){}


	/// return next item
	inline CC_L2D*		next		(void)
		{ return LipN; }


	/// return previous item
	inline CC_L2D*		prev		(void)
		{ return LipP; }


	/// insert an item after this item
	inline void			insAfter	(CC_HDL2D* pFth, class CC_L2D* pNew)
		{
			if (pFth == NULL)
				{
					Q_ASSERT(0);
					return;
				}
			pNew->LipN = LipN;
			pNew->LipP = this;
			if (LipN != NULL)
				{ /* not last item */
					pNew->LipN->LipP = pNew;
				}
			LipN = pNew;
			pFth->ackAdd(pNew);
		};


	/// insert an item before this item
	inline void			insBefore	(CC_HDL2D* pFth, class CC_L2D* pNew)
		{
			if (pFth == NULL)
				{
					Q_ASSERT(0);
					return;
				}
			pFth->ackAdd(pNew);

			pNew->LipN = this;
			pNew->LipP = LipP;
			if (LipP != NULL)
				{ /* not first item */
					LipP->LipN = pNew;
				}
			LipP = pNew;
			pFth->ackAdd(pNew);
		};


	/// extract this item from the chain
	inline void			extract		(CC_HDL2D* pFth)
		{
			if (pFth == NULL)
				{
					Q_ASSERT(0);
					return;
				}
			pFth->ackDel(this);
			if (LipN != NULL)
				{
					LipN->LipP = LipP;
				}
			if (LipP != NULL)
				{
					LipP->LipN = LipN;
				}
			LipP = NULL;
			LipN = NULL;
		};


	/// gets the index of a particular item inside the father
	inline int			index		( const CC_HDL2D* pFth) const
		{
			if (pFth == NULL)
				{
					Q_ASSERT(0);
					return -1;
				}
			CC_L2D*	pItr = pFth->first();
			int		iRet = 0;
			while (pItr != NULL)
				{
					if (pItr == this) return iRet;
					iRet++;
					pItr = pItr->next();
				}
			return -1;
		}


	/*  FUNCTIONS    =========================================================== */
	//
	//
	//
	//
};	/*	class	CC_L2D	*/
//
//
//
//
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
/* ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| */




/// get nth item
inline CC_L2D*		CC_HDL2D::item	( int i)  const
{
	CC_L2D* pRet;
	if (i >= iCnt) return NULL;
	pRet = Lip1;
	for (int j = 0; j < i; j++)
		{
			if (pRet == NULL)
				{
					Q_ASSERT(0);
					//iCnt = j;
					return NULL;
				}
			pRet = pRet->next();
		}
	return pRet;
}


/// tell if an item is part of this chain
inline bool			CC_HDL2D::has		( const CC_L2D* pIt)  const
{ return (pIt->index(this) != -1); }
/// tell if an item is part of this chain
inline int			CC_HDL2D::itemIndex	( const CC_L2D* pIt)  const
{ return pIt->index(this); }


/// append an item (insert after last)
inline void			CC_HDL2D::append	(CC_L2D* pIt)
{
	CC_L2D*		pLst;
	pLst = last();
	if (pLst == NULL)
		{ Lip1 = pIt; iCnt = 1; }
	else
		pLst->insAfter(this, pIt);
}


/// prepend an item (insert as first item)
inline void			CC_HDL2D::prepend	(CC_L2D* pIt)
{
	CC_L2D*		pLst;
	pLst = first();
	if (pLst == NULL)
		{ Lip1 = pLst; iCnt = 1; }
	else
		pLst->insBefore(this, pIt);
}


/// remove the item at given index
inline void			CC_HDL2D::remove	( const int i)
{
	CC_L2D*	pIt = item(i);
	if (pIt != NULL)
		{
			pIt->extract(this);
		}
}

/// remove a particular item
inline void			CC_HDL2D::remove	( CC_L2D* pIt)
{
	if (pIt != NULL)
		{
			pIt->extract(this);
		}
}

/// header is informed about an item being added
inline void			CC_HDL2D::ackAdd	(CC_L2D* pNew)
{
	if (pNew == NULL)
		{
			Q_ASSERT(0);
			return;
		}
	if (pNew->LipP == NULL)
		{
			Lip1 = pNew;
		}
	iCnt++;
}


/// header is informed about an item being deleted
inline void			CC_HDL2D::ackDel	(CC_L2D* pNew)
{
	if (pNew == NULL)
		{
			Q_ASSERT(0);
			return;
		}
	if (pNew == Lip1)
		{
			Lip1 = pNew->LipN;
		}
	iCnt--;
}







#endif	//	__cplusplus
#endif	//	__CC_L2D_INC__
/* ------------------------------------------------------------------------- */
/* ========================================================================= */


